﻿/*
 
 My English is terrible, however concidero a good practice to place the comments in a language that is used globally. 
 If you think you can improve the translation of the comments, I would appreciate. 
  
 Disclaimer: Although it should be easy to display a dialog that allows you to select a computer network, 
 is not much information online about it, after much searching, 
 I found some code on the blog about 
 Maxim Alexeyev in: http://discoveringdotnet.alexeyev.org/2008/04/how-to-browse-for-computer-name.html. 
 
 Part of code in namespace "EasyWindowsServiceManager.Dialogs.NetBrowser" I have taken from the above address. 
 Although I found no copyright terms, please retain this comment to respect the rights of authors 
 and do not detract from who actually made the code. 
  */

using System;
using System.Runtime.InteropServices;

namespace EasyWindowsServiceManager.Dialogs.NetBrowser
{
    internal delegate int BrowseCallBackProc(IntPtr hwnd, int msg, IntPtr lp, IntPtr wp);

    [StructLayout(LayoutKind.Sequential)]
    internal struct BrowseInfo
    {
        public IntPtr hwndOwner;
        public IntPtr pidlRoot;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string displayName;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string title;
        public int flags;
        [MarshalAs(UnmanagedType.FunctionPtr)]
        public BrowseCallBackProc callback;
        public IntPtr lparam;
    }

    [ComImport]
    [Guid("00000002-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IMalloc
    {
        [PreserveSig]
        IntPtr Alloc(IntPtr cb);

        [PreserveSig]
        IntPtr Realloc(IntPtr pv, IntPtr cb);

        [PreserveSig]
        void Free(IntPtr pv);

        [PreserveSig]
        IntPtr GetSize(IntPtr pv);

        [PreserveSig]
        int DidAlloc(IntPtr pv);

        [PreserveSig]
        void HeapMinimize();
    }

    /// <summary>
    /// A class that defines all the unmanaged methods used in the assembly
    /// </summary>
    internal class UnmanagedMethods
    {
        [DllImport("Shell32.dll", CharSet = CharSet.Auto)]
        internal extern static System.IntPtr SHBrowseForFolder(ref BrowseInfo bi);

        [DllImport("Shell32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal extern static bool SHGetPathFromIDList(IntPtr pidl, [MarshalAs(UnmanagedType.LPTStr)] System.Text.StringBuilder pszPath);

        [DllImport("User32.Dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal extern static bool SendMessage(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp);

        [DllImport("Shell32.dll")]
        internal extern static int SHGetMalloc([MarshalAs(UnmanagedType.IUnknown)]out object shmalloc);

        [DllImport("user32.dll")]
        internal extern static IntPtr GetActiveWindow();

        [DllImport("shell32.dll")]
        public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, ref IntPtr ppidl);

        //Helper routine to free memory allocated using shells malloc object
        internal static void SHMemFree(IntPtr ptr)
        {
            object shmalloc = null;

            if (SHGetMalloc(out shmalloc) == 0)
            {
                IMalloc malloc = (IMalloc)shmalloc;

                (malloc).Free(ptr);
            }
        }
    }
}
